<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>CSRF</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
    <link rel="stylesheet" href="../../plugins/fontawesome-free/css/all.min.css">
    <link rel="stylesheet" href="../../plugins/overlayScrollbars/css/OverlayScrollbars.min.css">
    <link rel="stylesheet" href="../../dist/css/adminlte.min.css">
</head>
<body class="hold-transition dark-mode sidebar-mini layout-fixed layout-navbar-fixed layout-footer-fixed">
<div class="wrapper">
    <nav id="Navbar" class="main-header navbar navbar-expand navbar-dark"></nav>
    <aside id="Container" class="main-sidebar sidebar-dark-primary elevation-4"></aside>
    <div class="content-wrapper" id="Wrapper">
        <section class="content-header" id="WrapperHeader"></section>
        <section class="content">
            <div class="container-fluid">
                <div id="notice"></div>
                <div class="card card-primary card-outline">
                    <div class="card-header">
                        <h3 class="card-title">CSRF Token</h3>
                    </div>
                    <div class="card-body">
                        <div class="card card-primary">
                            <div class="card-header">
                                <h3 class="card-title">后台登录</h3>
                            </div>
                            <form action="" onsubmit="return false" id="Login">
                                <div class="card-body">
                                    <div class="form-group">
                                        <label for="username">用户名</label>
                                        <input type="text" class="form-control" name="username" id="username" placeholder="Enter username">
                                    </div>
                                    <div class="form-group">
                                        <label for="password">密码</label>
                                        <input type="password" class="form-control" name="password" id="password" placeholder="Password">
                                    </div>
                                </div>
                                <div class="card-footer">
                                    <button type="submit" class="btn btn-primary" onclick="doLogin()">登录</button>
                                </div>
                            </form>
                        </div>
                    </div>
                    <div class="card-body">
                        <div class="card card-primary">
                            <div class="card-header">
                                <h3 class="card-title">修改个人信息</h3>
                            </div>
                            <form  action="" onsubmit="return false" id="info">
                                <div class="card-body">
                                    <div class="form-group">
                                        <label for="phone">手机号</label>
                                        <input type="text" class="form-control" id="phone" placeholder="Enter phone">
                                    </div>
                                    <div class="form-group">
                                        <label for="address">地址</label>
                                        <input type="text" class="form-control" id="address" placeholder="Enter address">
                                    </div>
                                </div>
                                <div class="card-footer">
                                    <button type="submit" class="btn btn-primary" onclick="updateInfo()">确认修改</button>
                                </div>
                                <input type="hidden" name="csrf_token" id="csrf_token">
                            </form>
                        </div>
                    </div>
                </div>
                <div class="card card-primary card-outline" id="showSource">
                    <div class="card-header">
                        <h3 class="card-title">源代码&amp;提示</h3>
                    </div>
                    <div class="card-body">
                        <div>
                            <p>这里需要先进行登录，相信你已经在暴力破解处已经收集到了不同的账户。这里还是想做一个提醒：</p>
                            <p>数据库中默认存在三个账户，分别是 admin、user1、test</p>
                            <p>这里修改个人资料的接口增加了一个参数 csrf_token 用来预防 CSRF。</p>
                            <p>但仔细观察，这个 csrf_token 用完之后不会直接过期。Session 设置了30分钟过期，也就是说你可以在着30分钟内进行CSRF攻击。</p>
                            <p><strong>代码实现</strong></p>
                            <pre><code>&#x20;&#x20;&#x20;&#x20;&commat;&#x41;&#x70;&#x69;&lpar;&lcub;&#x52;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&#x4D;&#x65;&#x74;&#x68;&#x6F;&#x64;&#x54;&#x79;&#x70;&#x65;&period;&#x50;&#x4F;&#x53;&#x54;&comma;&#x20;&#x52;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&#x4D;&#x65;&#x74;&#x68;&#x6F;&#x64;&#x54;&#x79;&#x70;&#x65;&period;&#x47;&#x45;&#x54;&rcub;&rpar;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x70;&#x75;&#x62;&#x6C;&#x69;&#x63;&#x20;&#x4D;&#x61;&#x70;&lt;&quest;&comma;&#x20;&quest;&gt;&#x20;&#x65;&#x64;&#x69;&#x74;&#x49;&#x6E;&#x66;&#x6F;&#x57;&#x69;&#x74;&#x68;&#x54;&#x6F;&#x6B;&#x65;&#x6E;&lpar;&#x48;&#x74;&#x74;&#x70;&#x53;&#x65;&#x72;&#x76;&#x6C;&#x65;&#x74;&#x52;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&#x20;&#x72;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&comma;&#x20;&#x48;&#x74;&#x74;&#x70;&#x53;&#x65;&#x72;&#x76;&#x6C;&#x65;&#x74;&#x52;&#x65;&#x73;&#x70;&#x6F;&#x6E;&#x73;&#x65;&#x20;&#x72;&#x65;&#x73;&#x70;&#x6F;&#x6E;&#x73;&#x65;&rpar;&#x20;&#x74;&#x68;&#x72;&#x6F;&#x77;&#x73;&#x20;&#x53;&#x65;&#x72;&#x76;&#x6C;&#x65;&#x74;&#x45;&#x78;&#x63;&#x65;&#x70;&#x74;&#x69;&#x6F;&#x6E;&comma;&#x20;&#x49;&#x4F;&#x45;&#x78;&#x63;&#x65;&#x70;&#x74;&#x69;&#x6F;&#x6E;&#x20;&lcub;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x53;&#x74;&#x72;&#x69;&#x6E;&#x67;&#x20;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&#x20;&equals;&#x20;&#x72;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&period;&#x67;&#x65;&#x74;&#x50;&#x61;&#x72;&#x61;&#x6D;&#x65;&#x74;&#x65;&#x72;&lpar;&quot;&#x63;&#x73;&#x72;&#x66;&lowbar;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&quot;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x48;&#x74;&#x74;&#x70;&#x53;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&#x20;&#x73;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&#x20;&equals;&#x20;&#x72;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&period;&#x67;&#x65;&#x74;&#x53;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&lpar;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x53;&#x74;&#x72;&#x69;&#x6E;&#x67;&#x20;&#x76;&lowbar;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&#x20;&equals;&#x20;&#x73;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&period;&#x67;&#x65;&#x74;&#x41;&#x74;&#x74;&#x72;&#x69;&#x62;&#x75;&#x74;&#x65;&lpar;&quot;&#x63;&#x73;&#x72;&#x66;&lowbar;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&quot;&rpar;&#x20;&excl;&equals;&#x20;&#x6E;&#x75;&#x6C;&#x6C;&#x20;&quest;&#x20;&#x53;&#x74;&#x72;&#x69;&#x6E;&#x67;&period;&#x76;&#x61;&#x6C;&#x75;&#x65;&#x4F;&#x66;&lpar;&#x73;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&period;&#x67;&#x65;&#x74;&#x41;&#x74;&#x74;&#x72;&#x69;&#x62;&#x75;&#x74;&#x65;&lpar;&quot;&#x63;&#x73;&#x72;&#x66;&lowbar;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&quot;&rpar;&rpar;&#x20;&colon;&#x20;&#x6E;&#x75;&#x6C;&#x6C;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x48;&#x61;&#x73;&#x68;&#x4D;&#x61;&#x70;&lt;&#x53;&#x74;&#x72;&#x69;&#x6E;&#x67;&comma;&#x20;&#x42;&#x6F;&#x6F;&#x6C;&#x65;&#x61;&#x6E;&gt;&#x20;&#x64;&#x61;&#x74;&#x61;&#x20;&equals;&#x20;&#x6E;&#x65;&#x77;&#x20;&#x48;&#x61;&#x73;&#x68;&#x4D;&#x61;&#x70;&lt;&gt;&lpar;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x69;&#x66;&#x20;&lpar;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&#x20;&equals;&equals;&#x20;&#x6E;&#x75;&#x6C;&#x6C;&#x20;&vert;&vert;&#x20;&excl;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&period;&#x65;&#x71;&#x75;&#x61;&#x6C;&#x73;&lpar;&#x76;&lowbar;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&rpar;&rpar;&lcub;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x64;&#x61;&#x74;&#x61;&period;&#x70;&#x75;&#x74;&lpar;&quot;&#x56;&#x65;&#x72;&#x69;&#x66;&#x69;&#x63;&#x61;&#x74;&#x69;&#x6F;&#x6E;&#x53;&#x74;&#x61;&#x74;&#x75;&#x73;&quot;&comma;&#x20;&#x66;&#x61;&#x6C;&#x73;&#x65;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x72;&#x65;&#x74;&#x75;&#x72;&#x6E;&#x20;&#x64;&#x61;&#x74;&#x61;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&rcub;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x72;&#x65;&#x74;&#x75;&#x72;&#x6E;&#x20;&#x65;&#x64;&#x69;&#x74;&#x49;&#x6E;&#x66;&#x6F;&lpar;&#x72;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&comma;&#x72;&#x65;&#x73;&#x70;&#x6F;&#x6E;&#x73;&#x65;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&rcub;&NewLine;&#x20;&#x20;&#x20;&#x20;&commat;&#x41;&#x70;&#x69;&lpar;&lcub;&#x52;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&#x4D;&#x65;&#x74;&#x68;&#x6F;&#x64;&#x54;&#x79;&#x70;&#x65;&period;&#x47;&#x45;&#x54;&rcub;&rpar;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x70;&#x75;&#x62;&#x6C;&#x69;&#x63;&#x20;&#x4D;&#x61;&#x70;&lt;&quest;&comma;&#x20;&quest;&gt;&#x20;&#x67;&#x65;&#x74;&#x54;&#x6F;&#x6B;&#x65;&#x6E;&lpar;&#x48;&#x74;&#x74;&#x70;&#x53;&#x65;&#x72;&#x76;&#x6C;&#x65;&#x74;&#x52;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&#x20;&#x72;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&comma;&#x20;&#x48;&#x74;&#x74;&#x70;&#x53;&#x65;&#x72;&#x76;&#x6C;&#x65;&#x74;&#x52;&#x65;&#x73;&#x70;&#x6F;&#x6E;&#x73;&#x65;&#x20;&#x72;&#x65;&#x73;&#x70;&#x6F;&#x6E;&#x73;&#x65;&rpar;&lcub;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x53;&#x74;&#x72;&#x69;&#x6E;&#x67;&#x20;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&#x20;&equals;&#x20;&#x75;&#x64;&#x69;&period;&#x67;&#x65;&#x74;&#x56;&#x65;&#x72;&#x69;&#x66;&#x69;&#x63;&#x61;&#x74;&#x69;&#x6F;&#x6E;&#x54;&#x6F;&#x6B;&#x65;&#x6E;&lpar;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x48;&#x74;&#x74;&#x70;&#x53;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&#x20;&#x73;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&#x20;&equals;&#x20;&#x72;&#x65;&#x71;&#x75;&#x65;&#x73;&#x74;&period;&#x67;&#x65;&#x74;&#x53;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&lpar;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x73;&#x65;&#x73;&#x73;&#x69;&#x6F;&#x6E;&period;&#x73;&#x65;&#x74;&#x41;&#x74;&#x74;&#x72;&#x69;&#x62;&#x75;&#x74;&#x65;&lpar;&quot;&#x63;&#x73;&#x72;&#x66;&lowbar;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&quot;&comma;&#x20;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x48;&#x61;&#x73;&#x68;&#x4D;&#x61;&#x70;&lt;&#x53;&#x74;&#x72;&#x69;&#x6E;&#x67;&comma;&#x20;&#x53;&#x74;&#x72;&#x69;&#x6E;&#x67;&gt;&#x20;&#x64;&#x61;&#x74;&#x61;&#x20;&equals;&#x20;&#x6E;&#x65;&#x77;&#x20;&#x48;&#x61;&#x73;&#x68;&#x4D;&#x61;&#x70;&lt;&gt;&lpar;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x64;&#x61;&#x74;&#x61;&period;&#x70;&#x75;&#x74;&lpar;&quot;&#x63;&#x73;&#x72;&#x66;&lowbar;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&quot;&comma;&#x20;&#x74;&#x6F;&#x6B;&#x65;&#x6E;&rpar;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&#x72;&#x65;&#x74;&#x75;&#x72;&#x6E;&#x20;&#x64;&#x61;&#x74;&#x61;&semi;&NewLine;&#x20;&#x20;&#x20;&#x20;&rcub;</code></pre>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </div>
</div>

    <aside class="control-sidebar control-sidebar-dark">
        <!-- Control sidebar content goes here -->
    </aside>
    <footer class="main-footer"></footer>
    <script src="../../dist/js/templateHandle.js"></script>
    <script>
        setWrapperHeader("CSRF", ["CSRF Token"]);
    </script>
    <script src="../../plugins/jquery/jquery.min.js"></script>
    <script src="../../plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
    <script src="../../plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js"></script>
    <script src="../../dist/js/adminlte.js"></script>
    <script>
        getToken();
        function getToken(){
            $.get({
                url: `${project_name}/csrf/getToken`,
                success(resp) {
                    console.log(resp)
                    if (resp["csrf_token"]){
                        $("#csrf_token")[0].value =  resp["csrf_token"];
                    }
                }
            })
        }
        const notice_dom = $("#notice")[0];
        const out_msg = "<a href='#' onClick='loginOut()' style='color: #6db3ff;'>点击登出</a>";
        if (document.cookie!=='' && window.localStorage.getItem('user_name')!==null&&document.cookie.indexOf("token")!==-1){
            notice_dom.innerHTML = generateNote("登录成功！欢迎 " + window.localStorage.getItem('user_name') + " 修改个人信息。" + out_msg);
            showForm(2)
            showInfo();
        } else {
            showForm(1)
        }
        function doLogin(){
            let data = {
                username: $("#username")[0].value,
                password: $("#password")[0].value,
            }
            if (data.username.length <= 0 && data.username.length <= 0)return false;
            $.post({
                url: `${project_name}csrf/loginWithCookie`,
                data,
                dataType: "json",
                success(resp){
                    console.log(resp)
                    if(resp["loginStatus"]){
                        showInfo();
                        showForm(2);
                    } else {
                        notice_dom.innerHTML = generateNote("登录失败，账号或者密码错误！");
                    }
                }
            })
        }

        function showInfo(){
            $.get({
                url: `${project_name}csrf/showInfo`,
                xhrFields: {
                    withCredentials: true
                },
                success(resp) {
                    if (!resp['loginStatus'])return;
                    window.localStorage.setItem('user_name', resp['userName']);
                    notice_dom.innerHTML = generateNote("登录成功！欢迎 " +  resp['userName'] + " 修改个人信息。" + out_msg);
                    let userData = resp['userData'];
                    $("#phone")[0].value = userData.phone;
                    $("#address")[0].value = userData.address;
                }
            })
        }

        function updateInfo(){
            let data = {
                phone : $("#phone")[0].value,
                address: $("#address")[0].value,
                csrf_token: $("#csrf_token")[0].value,
            }
            $.post({
                url: `${project_name}/csrf/editInfo`,
                data,
                xhrFields: {
                    withCredentials: true
                },
                dataType: "json",
                success(resp){
                    console.log(resp)
                    if(!resp["loginStatus"])return;
                    if(resp['updateStatus'])notice_dom.innerHTML = generateNote("修改成功！");
                    window.location.reload();
                }
            })
        }

        function showForm(index){
            let forms = $("#Wrapper > section.content > div > div.card.card-primary.card-outline > div:nth-child(n+2)")
            forms[0].style  = index === 1 ? "display:block" : "display:none"
            forms[1].style  = index === 2 ? "display:block" : "display:none"
        }

        function loginOut(){
            document.cookie = '';
            showForm(1);
            notice_dom.innerHTML='';
            $.get({
                url: `${project_name}csrf/loginOut`,
                xhrFields: {
                    withCredentials: true
                },
                success(resp) {
                    location.reload();
                }
            })
        }
    </script>
</body>
</html>